Previous approaches to answering a query on a database involve exhaustive search, space-partitioned search, pigeonholing, and hashing. Exhaustive search involves searching through the entire database to find those rows which “match” the query. Space-partitioned search involves searching through a database, which has been partitioned into a hierarchy of nodes for faster search. Space partitioning methods including kd-trees, metric trees, M-trees, R*-trees, vp-trees, vantage point trees, vantage point forests, multi-vantage point trees, bisector trees, Orchard's algorithm, random projections, fixed queries trees, Voronoi trees, BBD-trees, min-wise independent permutations, Burkhard-Keller trees, generalized hyper-plane trees, geometric near-neighbor access trees (GNAT), and spatial approximation trees (SAT). Pigeonholing involves putting each row into a bucket based on the row's contents. Hashing involves transforming the query into an index, which can then be used to determine those locations of the database to search. These conventional approaches have several shortcomings. Exhaustive search does not scale up as the database size grows. Space partitioning does not scale up as the number of dimensions of a row grows. This is because the number of partitions per node is typically 2n where n is the number of dimensions. Thus, when n is large, exhaustive search becomes more efficient than space-partitioned search. Pigeonholing suffers from boundary confusion because a query can be placed in one bucket when the query is actually closer to a row in another bucket. Hashing cannot directly be used to find a “nearest” match. Finally, these conventional approaches also cannot handle missing data nor can they extrapolate beyond or interpolate between rows in the database.